package com.ruoyi.system.controller;

import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.component.SmsComponent;
import com.ruoyi.system.constant.AuthServiceConstant;
import com.ruoyi.system.domain.Vo.CaptchaVo;
import com.ruoyi.system.domain.Vo.LoginUserVo;
import com.ruoyi.system.domain.Vo.UsersVo;
import com.ruoyi.system.service.IUsersService;
import com.ruoyi.system.utils.BizCodeEnum;
import com.ruoyi.system.utils.validate.AddGroup;
import com.ruoyi.system.utils.validate.EditGroup;
import com.ruoyi.system.utils.validate.LoginGroup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpSession;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

/**
 * @Description: TODO
 * @Author: jsj
 * @Date: 2022/8/18
 */
@RestController
@RequestMapping("/system/login")
@Anonymous
public class LoginController extends BaseController {

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    SmsComponent smsComponent;

    @Autowired
    IUsersService iUsersService;

    /**
     * 获取手机验证码
     * @param captchaVo
     * @return
     */
    @PostMapping("/sms/sendcode")
    @Anonymous
    public R getPhoneMsgCode(@RequestBody CaptchaVo captchaVo){

        String mobile = captchaVo.getUserPhone();
        System.out.println(mobile);

        //用于手机号验证，验证手机号是否合法
        if (mobile==null
                || !Pattern.matches("^1[3-9]\\d{9}$", mobile)) {
            return R.fail(BizCodeEnum.ILLEGAL_PHONE_EXCEPTION.getCode()
                    ,BizCodeEnum.ILLEGAL_PHONE_EXCEPTION.getMsg());
        }

        // TODO: 2022/6/9 1、接口防刷
        //1、判断当前手机号是否在有效期内持有验证码
        String redisCode = !captchaVo.isUpdate() ?
                stringRedisTemplate.opsForValue().get(AuthServiceConstant.SMS_CODE_CACHE_PREFIX + mobile)
                :stringRedisTemplate.opsForValue().get(AuthServiceConstant.SMS_CODE_CACHE_UPDATE_PREFIX + mobile);

        if (!StringUtils.isEmpty(redisCode) && redisCode !="") {
            long l = Long.parseLong(redisCode.split("_")[1]);
            //60s内不能再次发送
            if(System.currentTimeMillis() - l < 60000){
                return R.fail(BizCodeEnum.SMS_CODE_EXCEPTION.getCode(),
                        BizCodeEnum.SMS_CODE_EXCEPTION.getMsg());
            }
        }

        //2、验证码的再次校验。redis。存key-mobile，value-authCode
        //生成六位数验证码  数字验证码
        String authCode = String.valueOf(new Random().nextInt(899999) + 100000);
        redisCode = authCode + "_" + System.currentTimeMillis();

        //redis缓存验证码，防止同一个mobile在60s内再次发送验证码
        String prefix = captchaVo.isUpdate() ? AuthServiceConstant.SMS_CODE_CACHE_UPDATE_PREFIX : AuthServiceConstant.SMS_CODE_CACHE_PREFIX;
        System.out.println(prefix);
        stringRedisTemplate.opsForValue()
                .set(prefix + mobile, redisCode,
                        10, TimeUnit.MINUTES);

        System.out.println("发送验证码:"+mobile+"--->"+authCode);

        //调用发送手机验证码组件
        smsComponent.sendSmsCode(mobile,authCode);

        return R.ok().put("data","已发送验证码");
    }

    @PostMapping("/sms/register")
    public AjaxResult register(@Validated(AddGroup.class) @RequestBody UsersVo usersVo){

        System.out.println(usersVo);

        //1、校验验证码
        String phoneCaptcha = usersVo.getPhoneCaptcha();
        String s = stringRedisTemplate.opsForValue().get(AuthServiceConstant.SMS_CODE_CACHE_PREFIX + usersVo.getUserPhone());

        System.out.println("当前手机号："+ usersVo.getUserPhone()
                + "-----> 输入:" + usersVo.getPhoneCaptcha()
                + "-----> 查询:" + s);

        // System.out.println(s.split("_")[0]);

        if (!StringUtils.isEmpty(s)){
            if (phoneCaptcha.equals(s.split("_")[0])) {
                //使用验证码后删除redis中的验证码   令牌机制
                stringRedisTemplate.delete(AuthServiceConstant.SMS_CODE_CACHE_PREFIX + usersVo.getUserPhone());
                //注册方法
                if (iUsersService.registerUser(usersVo)) {
                    //注册成功
                    return AjaxResult.success();
                }
            }
        }
        //注册失败，验证码错误
        return AjaxResult.error(BizCodeEnum.PHONE_CAPTCHA_EXCEPTION.getCode()
                ,BizCodeEnum.PHONE_CAPTCHA_EXCEPTION.getMsg());
    }

    @PostMapping("/sms/updateUser")
    public AjaxResult updateUser(@Validated(EditGroup.class) @RequestBody UsersVo usersVo){

        System.out.println(usersVo);

        //1、校验验证码
        String phoneCaptcha = usersVo.getPhoneCaptcha();
        String s = stringRedisTemplate.opsForValue().get(AuthServiceConstant.SMS_CODE_CACHE_UPDATE_PREFIX + usersVo.getUserPhone());

        System.out.println("当前手机号："+ usersVo.getUserPhone()
                + "-----> 输入:" + usersVo.getPhoneCaptcha()
                + "-----> 查询:" + s);

        if (!StringUtils.isEmpty(s)){
            if (phoneCaptcha.equals(s.split("_")[0])) {
                //使用验证码后删除redis中的验证码   令牌机制
                stringRedisTemplate.delete(AuthServiceConstant.SMS_CODE_CACHE_UPDATE_PREFIX + usersVo.getUserPhone());
                //注册方法
                if (iUsersService.registerUser(usersVo)) {
                    //注册成功
                    return AjaxResult.success();
                }
            }
        }
        //注册失败，验证码错误
        return AjaxResult.error(BizCodeEnum.PHONE_CAPTCHA_EXCEPTION.getCode()
                ,BizCodeEnum.PHONE_CAPTCHA_EXCEPTION.getMsg());
    }

    @Anonymous
    @PostMapping("/login")
    public AjaxResult login(@Validated(LoginGroup.class) @RequestBody UsersVo usersVo, HttpSession httpSession){
        // System.out.println("进入登录方法");
        boolean flag = false;
        LoginUserVo loginUserVo = iUsersService.userLogin(usersVo);
        // //登录成功放到session中
        // httpSession.setAttribute(AuthServiceConstant.LOGIN_USER, loginUserVo);

        // 登录成功将当前用户存储到redis中,有效期为30min
        stringRedisTemplate.opsForValue().set(
                AuthServiceConstant.LOGIN_USER, loginUserVo.toString(),
                30, TimeUnit.MINUTES);

        //判断用户是否为空
        if (loginUserVo!=null) {
            flag = true;
        }

        return flag ? AjaxResult.success() : AjaxResult.error();
    }

    /**
     * 判断当前用户是否登录
     * @return
     */
    @PostMapping("/isLogin")
    public AjaxResult isLogin(){
        //获取当前登录用户信息
        String loginUser = stringRedisTemplate.opsForValue().get(AuthServiceConstant.LOGIN_USER);
        //用户未登录
        if (loginUser == null || loginUser.equals("")) {
            return AjaxResult.error().put("errorData", "用户未登录");
        }
        return AjaxResult.success();
    }
}
